package cn.openea.perpartner.payment.web.points.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.openea.perpartner.common.redis.service.RedisCache;
import cn.openea.perpartner.payment.web.points.dto.TokenVo;
import cn.openea.perpartner.payment.web.points.service.IValidateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Weird077
 * @description TODO
 * @date 2022-11-18 10:57
 */
@Service
public class ValidateServiceImpl implements IValidateService {
    @Value("${wxpay.authsalt}")
    private String authsalt;

    @Value("${wxpay.tokenttl}")
    private int tokenttl;
    @Autowired
    private RedisCache redisCache;
    @Override
    public String createToken(TokenVo vo) {
        Map<String, Object> params = BeanUtil.beanToMap(vo);
        // 鉴权参数不参与计算
        params.remove("token");
        params.remove("authStr");
        // 随机8位盐
        String randomSalt = RandomUtil.randomString(6);
        // 将参数与随机8位盐混合再计算md5值
        String body = randomSalt + params;
        String token = SecureUtil.md5(body);
        // 以 token 为 key 随机8位盐为 value，将内容存到redis内有效时间为5秒
        redisCache.setCacheObject(token, randomSalt, tokenttl, TimeUnit.SECONDS);
        return token;
    }

    @Override
    public boolean validateToken(TokenVo vo) {
        Map<String, Object> params = BeanUtil.beanToMap(vo);
        // 从参数中获取鉴权参数 tempToken 和 authToken
        String token = (String) params.get("token");
        String authStr = (String) params.remove("authStr");
        if(StrUtil.isBlank(token) || StrUtil.isBlank(authStr)){
            return false;
        }
        // 从redis中获取随机8位盐
        String randomSalt = redisCache.getCacheObject(token);
        if (StrUtil.isBlank(randomSalt)) {
            return false;
        }
        params.remove("token");
        params.remove("authStr");
        // 验证 token 参数是否正确，来确定 params 数据是否被修改过
        String body = randomSalt + params;
        if(!token.equals(SecureUtil.md5(body))){
            // 表示参数被修改过了，不能进行处理
            return false;
        }
        // 再次通过 authToken 参数验证 数据是否是从 指定 authsalt 授权盐密码 的地方请求过来的 （WxPerPartner 12 的 长度）
        String tmpStr = authsalt.charAt(2) + authsalt.charAt(8) + token + authsalt.charAt(10) + authsalt.charAt(5);
        redisCache.deleteObject(token);
        // 表示请求来源不明
        return authStr.equals(SecureUtil.md5(tmpStr));
    }
}
